﻿/* ================================================================================
<copyright file="ExtendedLogManager.cs" company="The Framework Factory, LLC" lastWriteTime="12/05/2012 23:23:47 PM">
  Copyright (c) 2012 The Framework Factory, LLC.  All rights reserved.
</copyright>
=================================================================================== */
using System;
using System.Reflection;

using log4net.Core;

namespace FWF.Logging
{
    /// <summary>
    /// A log manager for the extended logging levels.
    /// </summary>
    public static class ExtendedLogManager
    {
        /// <summary>
        /// The wrapper map to use to hold the <see cref="ExtendedLogImplementation"/> objects
        /// </summary>
        private static readonly WrapperMap _wrapperMap = new WrapperMap( WrapperCreationHandler );

        #region Type Specific Manager Methods

        /// <summary>
        /// Returns the named logger if it exists
        /// </summary>
        /// <remarks>
        /// <para>If the named logger exists (in the default hierarchy) then it
        /// returns a reference to the logger, otherwise it returns
        /// <c>null</c>.</para>
        /// </remarks>
        /// <param name="name">The fully qualified logger name to look for</param>
        /// <returns>The logger found, or null</returns>
        public static IFWFLog Exists( string name )
        {
            return Exists( Assembly.GetCallingAssembly(), name );
        }

        /// <summary>
        /// Returns the named logger if it exists
        /// </summary>
        /// <remarks>
        /// <para>If the named logger exists (in the specified domain) then it
        /// returns a reference to the logger, otherwise it returns
        /// <c>null</c>.</para>
        /// </remarks>
        /// <param name="domain">the domain to lookup in</param>
        /// <param name="name">The fully qualified logger name to look for</param>
        /// <returns>The logger found, or null</returns>
        public static IFWFLog Exists( string domain, string name )
        {
            return WrapLogger( LoggerManager.Exists( domain, name ) );
        }

        /// <summary>
        /// Returns the named logger if it exists
        /// </summary>
        /// <remarks>
        /// <para>If the named logger exists (in the specified assembly's domain) then it
        /// returns a reference to the logger, otherwise it returns
        /// <c>null</c>.</para>
        /// </remarks>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <param name="name">The fully qualified logger name to look for</param>
        /// <returns>The logger found, or null</returns>
        public static IFWFLog Exists( Assembly assembly, string name )
        {
            return WrapLogger( LoggerManager.Exists( assembly, name ) );
        }

        /// <summary>
        /// Returns all the currently defined loggers in the default domain.
        /// </summary>
        /// <remarks>
        /// <para>The root logger is <b>not</b> included in the returned array.</para>
        /// </remarks>
        /// <returns>All the defined loggers</returns>
        public static IFWFLog[] GetCurrentLoggers()
        {
            return GetCurrentLoggers( Assembly.GetCallingAssembly() );
        }

        /// <summary>
        /// Returns all the currently defined loggers in the specified domain.
        /// </summary>
        /// <param name="domain">the domain to lookup in</param>
        /// <remarks>
        /// The root logger is <b>not</b> included in the returned array.
        /// </remarks>
        /// <returns>All the defined loggers</returns>
        public static IFWFLog[] GetCurrentLoggers( string domain )
        {
            return WrapLoggers( LoggerManager.GetCurrentLoggers( domain ) );
        }

        /// <summary>
        /// Returns all the currently defined loggers in the specified assembly's domain.
        /// </summary>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <remarks>
        /// The root logger is <b>not</b> included in the returned array.
        /// </remarks>
        /// <returns>All the defined loggers</returns>
        public static IFWFLog[] GetCurrentLoggers( Assembly assembly )
        {
            return WrapLoggers( LoggerManager.GetCurrentLoggers( assembly ) );
        }

        /// <summary>
        /// Retrieve or create a named logger.
        /// </summary>
        /// <remarks>
        /// <para>Retrieve a logger named as the <paramref name="name"/>
        /// parameter. If the named logger already exists, then the
        /// existing instance will be returned. Otherwise, a new instance is
        /// created.</para>
        /// 
        /// <para>By default, loggers do not have a set level but inherit
        /// it from the hierarchy. This is one of the central features of
        /// log4net.</para>
        /// </remarks>
        /// <param name="name">The name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IFWFLog GetLogger( string name )
        {
            return GetLogger( Assembly.GetCallingAssembly(), name );
        }

        /// <summary>
        /// Retrieve or create a named logger.
        /// </summary>
        /// <remarks>
        /// <para>Retrieve a logger named as the <paramref name="name"/>
        /// parameter. If the named logger already exists, then the
        /// existing instance will be returned. Otherwise, a new instance is
        /// created.</para>
        /// 
        /// <para>By default, loggers do not have a set level but inherit
        /// it from the hierarchy. This is one of the central features of
        /// log4net.</para>
        /// </remarks>
        /// <param name="domain">the domain to lookup in</param>
        /// <param name="name">The name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IFWFLog GetLogger( string domain, string name )
        {
            return WrapLogger( LoggerManager.GetLogger( domain, name ) );
        }

        /// <summary>
        /// Retrieve or create a named logger.
        /// </summary>
        /// <remarks>
        /// <para>Retrieve a logger named as the <paramref name="name"/>
        /// parameter. If the named logger already exists, then the
        /// existing instance will be returned. Otherwise, a new instance is
        /// created.</para>
        /// 
        /// <para>By default, loggers do not have a set level but inherit
        /// it from the hierarchy. This is one of the central features of
        /// log4net.</para>
        /// </remarks>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <param name="name">The name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IFWFLog GetLogger( Assembly assembly, string name )
        {
            return WrapLogger( LoggerManager.GetLogger( assembly, name ) );
        }

        /// <summary>
        /// Shorthand for LogManager.GetLogger(string).
        /// </summary>
        /// <param name="type">The full name of <paramref name="type"/> will
        /// be used as the name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        /// <remarks>
        /// Get the logger for the fully qualified name of the type specified.
        /// </remarks>
        public static IFWFLog GetLogger( Type type )
        {
            if ( type == null )
            {
                throw new ArgumentNullException( "type" );
            }

            return GetLogger( Assembly.GetCallingAssembly(), type.FullName );
        }

        /// <summary>
        /// Shorthand for LogManager.GetLogger(string).
        /// </summary>
        /// <remarks>
        /// Get the logger for the fully qualified name of the type specified.
        /// </remarks>
        /// <param name="domain">the domain to lookup in</param>
        /// <param name="type">The full name of <paramref name="type"/> will 
        /// be used as the name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IFWFLog GetLogger( string domain, Type type )
        {
            return WrapLogger( LoggerManager.GetLogger( domain, type ) );
        }

        /// <summary>
        /// Shorthand for LogManager.GetLogger(string).
        /// </summary>
        /// <remarks>
        /// Get the logger for the fully qualified name of the type specified.
        /// </remarks>
        /// <param name="assembly">the assembly to use to lookup the domain</param>
        /// <param name="type">The full name of <paramref name="type"/> will 
        /// be used as the name of the logger to retrieve.</param>
        /// <returns>the logger with the name specified</returns>
        public static IFWFLog GetLogger( Assembly assembly, Type type )
        {
            return WrapLogger( LoggerManager.GetLogger( assembly, type ) );
        }

        #endregion

        #region Extension Handlers

        /// <summary>
        /// Lookup the wrapper object for the logger specified
        /// </summary>
        /// <param name="logger">the logger to get the wrapper for</param>
        /// <returns>the wrapper for the logger specified</returns>
        private static IFWFLog WrapLogger( ILogger logger )
        {
            return (IFWFLog) _wrapperMap.GetWrapper( logger );
        }

        /// <summary>
        /// Lookup the wrapper objects for the loggers specified
        /// </summary>
        /// <param name="loggers">the loggers to get the wrappers for</param>
        /// <returns>
        /// Lookup the wrapper objects for the loggers specified
        /// </returns>
        private static IFWFLog[] WrapLoggers( ILogger[] loggers )
        {
            var results = new IFWFLog[ loggers.Length ];
            for ( int i = 0; i < loggers.Length; i++ )
            {
                results[ i ] = WrapLogger( loggers[ i ] );
            }
            return results;
        }

        /// <summary>
        /// Method to create the <see cref="ILoggerWrapper"/> objects used by
        /// this manager.
        /// </summary>
        /// <param name="logger">The logger to wrap</param>
        /// <returns>The wrapper for the logger specified</returns>
        private static ILoggerWrapper WrapperCreationHandler( ILogger logger )
        {
            return new ExtendedLogImplementation( logger );
        }

        #endregion


    }
}
